package cn.superchart.common.utils;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.superchart.common.annotate.FieldWhere;
import cn.superchart.common.enums.SearchEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

@Slf4j
public class QueryBuilder {


    public static void buildQueryParam(Object param,QueryWrapper queryWrapper){
        Field[] fields = ReflectUtil.getFields(param.getClass());
        if(Checker.BeNotEmpty(fields)){
            for(Field field:fields){
                FieldWhere fieldWhere = field.getAnnotation(FieldWhere.class);
                if(fieldWhere!=null){
                    SearchEnum type = fieldWhere.type();
                    switch (type) {
                        case EQ -> QueryBuilder.buildEq(param,field,fieldWhere,queryWrapper,true);
                        case NEQ -> QueryBuilder.buildEq(param,field,fieldWhere,queryWrapper,false);
                        case LIKE -> QueryBuilder.buildLike(param,field,fieldWhere,queryWrapper,true);
                        case NOT_LIKE -> QueryBuilder.buildLike(param,field,fieldWhere,queryWrapper,false);
                        case IN -> QueryBuilder.buildIn(param,field,fieldWhere,queryWrapper,true);
                        case NOT_IN -> QueryBuilder.buildIn(param,field,fieldWhere,queryWrapper,false);
                        case BETWEEN -> QueryBuilder.buildBetween(param,field,fieldWhere,queryWrapper,true);
                        case NOT_BETWEEN -> QueryBuilder.buildBetween(param,field,fieldWhere,queryWrapper,false);
                        case GT -> QueryBuilder.buildGt(param,field,fieldWhere,queryWrapper,true);
                        case LT -> QueryBuilder.buildGt(param,field,fieldWhere,queryWrapper,false);
                        case GTE -> QueryBuilder.buildGte(param,field,fieldWhere,queryWrapper,true);
                        case LTE -> QueryBuilder.buildGte(param,field,fieldWhere,queryWrapper,false);
                        case IS_NULL -> QueryBuilder.buildIsNull(field,fieldWhere,queryWrapper,true);
                        case IS_NOT_NULL -> QueryBuilder.buildIsNull(field,fieldWhere,queryWrapper,false);
                        default -> log.info("未找到查询条件");
                    }
                }
            }
        }
    }


    public static void buildEq(Object param, Field field, FieldWhere fieldWhere, QueryWrapper queryWrapper, Boolean isEq){
        String fieldName = fieldName(field,fieldWhere);
        Object value = fieldValue(field,param);
        if(isEq){
            queryWrapper.eq((Checker.BeNotNull(value) && !fieldWhere.queryEmpty()),fieldName,value);
        }else {
            queryWrapper.notIn(fieldName,value);
        }
    }

    public static void buildLike(Object param, Field field, FieldWhere fieldWhere,QueryWrapper queryWrapper,Boolean isLike){
        String fieldName = fieldName(field,fieldWhere);
        Object value = fieldValue(field,param);
        if(isLike)
            queryWrapper.like((Checker.BeNotNull(value) && !fieldWhere.queryEmpty()),fieldName,value);
        else
            queryWrapper.notLike((Checker.BeNotNull(value) && !fieldWhere.queryEmpty()),fieldName,value);
    }

    public static void buildIn(Object param, Field field, FieldWhere fieldWhere,QueryWrapper queryWrapper,Boolean isIn){
        String fieldName = fieldName(field,fieldWhere);
        Object value = fieldValue(field,param);
        if(isIn){
                if(value instanceof Collection){
                    queryWrapper.in((Checker.BeNotNull(value) && !fieldWhere.queryEmpty()),fieldName,(Collection) value);
                }else if(value instanceof Object[]){
                    queryWrapper.in((Checker.BeNotNull(value) && !fieldWhere.queryEmpty()),fieldName, Arrays.asList(value));
                }
        }
        else{
                if(value instanceof Collection){
                    queryWrapper.notIn((Checker.BeNotNull(value) && !fieldWhere.queryEmpty()),fieldName,(Collection) value);
                }else if(value instanceof Object[]){
                    queryWrapper.notIn((Checker.BeNotNull(value) && !fieldWhere.queryEmpty()),fieldName, Arrays.asList(value));
                }
            }

    }


    public static void buildBetween(Object param, Field field, FieldWhere fieldWhere,QueryWrapper queryWrapper,Boolean isBetween){
        String fieldName = fieldName(field,fieldWhere);
        Object value = fieldValue(field,param);
        if(isBetween){
            if(Checker.BeNotNull(value)){
                if(value instanceof Collection){
                    Collection values= (Collection) value;
                    List<String> list = new ArrayList<>(values);
                    if(Checker.BeNotEmpty(list)){
                        queryWrapper.between((Checker.BeNotEmpty(list) && list.size()==2),fieldName,list.get(0),list.get(1));
                    }
                }else if(value instanceof Object[]){
                    Object[] values= (Object[]) value;
                    if(Checker.BeNotEmpty(values)){
                        queryWrapper.between((Checker.BeNotEmpty(values) && values.length==2 ),fieldName, values[0],values[1]);
                    }
                }
            }
        }
        else{
            if(Checker.BeNotNull(value)){
                if(value instanceof Collection){
                    Collection values= (Collection) value;
                    List<String> list = new ArrayList<>(values);
                    queryWrapper.notBetween((Checker.BeNotEmpty(list) && list.size()==2),fieldName,list.get(0),list.get(1));
                }else if(value instanceof Object[]){
                    Object[] values= (Object[]) value;
                    queryWrapper.notBetween((Checker.BeNotEmpty(values) && values.length==2 ),fieldName, values[0],values[1]);
                }
            }
        }

    }



    public static void buildGt(Object param, Field field, FieldWhere fieldWhere,QueryWrapper queryWrapper,Boolean isGt){
        String fieldName = fieldName(field,fieldWhere);
        Object value = fieldValue(field,param);
        if(isGt)
            queryWrapper.gt((Checker.BeNotNull(value) && !fieldWhere.queryEmpty()),fieldName,value);
        else
            queryWrapper.lt((Checker.BeNotNull(value) && !fieldWhere.queryEmpty()),fieldName,value);
    }


    public static void buildGte(Object param, Field field, FieldWhere fieldWhere,QueryWrapper queryWrapper,Boolean isGte){
        String fieldName = fieldName(field,fieldWhere);
        Object value = fieldValue(field,param);
        if(isGte)
            queryWrapper.ge((Checker.BeNotNull(value) && !fieldWhere.queryEmpty()),fieldName,value);
        else
            queryWrapper.le((Checker.BeNotNull(value) && !fieldWhere.queryEmpty()),fieldName,value);
    }

    public static void buildIsNull( Field field, FieldWhere fieldWhere, QueryWrapper queryWrapper, boolean isNull) {
        String fieldName = fieldName(field,fieldWhere);
        if(isNull)
            queryWrapper.isNull(fieldName);
        else
            queryWrapper.isNotNull(fieldName);
    }

    private static String fieldName(Field field, FieldWhere fieldWhere){
        String fieldName = Checker.BeNotBlank(fieldWhere.fieldName())?fieldWhere.fieldName():field.getName();
        return StrUtil.toUnderlineCase(fieldName);
    }


    private static Object fieldValue(Field field, Object param){
         Object value = ReflectUtil.getFieldValue(param,field);
         if(Checker.BeNotNull(value)){
             if(value instanceof String){
                 if(Checker.BeBlank(value.toString())){
                     return null;
                 }
             }
         }
         return value;
    }

//    public static void main(String[] args) {
//        System.out.println(StrUtil.toCamelCase("GMT_CUR"));
//    }

}
